/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package msnclient;

import msncommonsc.GuardarC;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import msncommonsc.ClienteRMI;
import msncommonsc.Contacto;
import msncommonsc.EnumEstado;
import msncommonsc.MensajeDTO;
import msncommonsc.Persona;
import msncommonsc.ServidorRMI;

/**
 *
 * @author Martin
 */
public class Cliente extends UnicastRemoteObject implements ClienteRMI {

    private static Cliente instancia;
    private Persona p;
    private ServidorRMI servidor;

    public static Cliente getInstancia() throws RemoteException, NotBoundException {
        if (instancia == null) {
            instancia = new Cliente();
        }
        return instancia;
    }

    private Cliente() throws java.rmi.RemoteException, NotBoundException {
        super();
        Registry r = LocateRegistry.getRegistry("localhost", 8080);
        servidor = (ServidorRMI) r.lookup("SRMI");
    }

    public Persona getP() {
        return p;
    }

    public void setP(Persona p) {
        this.p = p;
    }

    @Override
    public Boolean crearCuenta(String nombre, String nick, String contraseña) throws RemoteException, NotBoundException {
        this.p = new Persona();
        this.getP().setNombre(nombre);
        this.getP().setNick(nick);
        this.getP().setContraseña(contraseña);
        this.getP().setMapaContactos(new ArrayList<Contacto>());
        Boolean crearCuenta = servidor.crearCuenta(p);
        try {
            if (crearCuenta.equals(true)) {
                System.out.println("cuenta creada");
                return crearCuenta;
            } else {
                System.out.println("cuenta no creada");
                return crearCuenta;
            }
        } catch (Exception e) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    @Override
    public Boolean desconectar() throws RemoteException {
        try {

            return servidor.desconectar(this.p.getNombre());
        } catch (Exception e) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    @Override
    public void notificarEstado(String nombre, EnumEstado estado) throws RemoteException {
        try {
            for (Contacto c : getP().getMapaContactos()) {
                if (c.getNombre().equals(nombre)) {
                    if (estado.equals(EnumEstado.INVISIBLE)) {
                        estado = EnumEstado.DESCONECTADO;
                    }
                    c.setEstado(estado.toString());
                    String s = (nombre + " Ha cambiado su Estado a " + estado.toString());
                    System.out.println(s);
                    Controladora.getInstancia().notificarEstado();
                }
            }
        } catch (Exception e) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    @Override
    public void notificarNick(String nick, String nombre) throws RemoteException {
        for (Contacto c : getP().getMapaContactos()) {
            if (c.getNombre().equals(nombre)) {
                c.setNick(nick);
                String s = (nombre + " Ha cambiado su nic a " + nick);
                System.out.println(s);
                try {
                    Controladora.getInstancia().notificarNick();
                } catch (RemoteException ex) {
                    Logger.getLogger(Cliente.class.getName()).log(Level.SEVERE, null, ex);
                } catch (NotBoundException ex) {
                    Logger.getLogger(Cliente.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }

    @Override
    public Boolean agregarContacto(String nombre) throws RemoteException {
        Contacto c = new Contacto();
        c.setNombre(nombre);
        boolean agregar = true;
        for (Contacto cont : this.p.getMapaContactos()) {
            if (cont.getNombre().equals(nombre)) {
                agregar = false;
            }
        }

        try {
            if (agregar) {
                this.p = servidor.agregarContacto(this.p, c);

            }
        } catch (Exception e) {
            throw new UnsupportedOperationException(e.toString());
        }
        return agregar;
    }

    @Override
    public Boolean enviarMensaje(String destino, String mensaje) throws RemoteException {
        try {
            MensajeDTO msj = new MensajeDTO();
            msj.setDestino(destino);
            msj.setOrigen(this.p.getNombre());
            msj.setMensaje(mensaje);
            if (this.p.isGuardarC()) {
                GuardarC g = GuardarC.getInstance();
                g.persistirMensaje(msj, true);
            }
            return servidor.enviarMensaje(msj);
        } catch (Exception e) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    @Override
    public int cambiarDatosPersonales(String nick, String contraseñaN, String contraseñaV) throws RemoteException {
        if (this.p.getContraseña().equals(contraseñaV) && !contraseñaN.equals("")) {
            this.p = servidor.cambiarDatosPersonales(this.p.getNombre(), contraseñaN, nick);
            if (!nick.equals("") && !contraseñaN.equals("")) {
                System.out.println(this.p.getNick() + " " + this.p.getContraseña());
                return 3;
            } else if (!contraseñaN.equals("")) {
                System.out.println(this.p.getContraseña());
                return 2;
            } else {
                return 0;
            }
        } else if (!nick.equals("")) {
            this.p = servidor.cambiarDatosPersonales(this.p.getNombre(), contraseñaN, nick);
            System.out.println(this.p.getNick());
            return 1;
        } else {
            return 0;
        }
    }

    @Override
    public void recibirMensaje(MensajeDTO mensaje) throws RemoteException {
        try {
            Controladora c = Controladora.getInstancia();
            c.recibirMensaje(mensaje);
            if (this.p.isGuardarC()) {
                GuardarC g = GuardarC.getInstance();
                g.persistirMensaje(mensaje, false);
            }
            String s = mensaje.getOrigen() + "  -->  " + mensaje.getMensaje();
            System.out.println(s);
        } catch (Exception e) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    @Override
    public void cambiarEstado(EnumEstado estado) throws RemoteException {
        this.getP().setEstado(estado.toString());
        servidor.cambiarEstado(this.p.getNombre(), estado);
    }

    @Override
    public Boolean conectar(String nombre, String contraseña) throws RemoteException {
        try {
            Persona persona = servidor.conectar(nombre, contraseña, this);
            if (!persona.getNombre().equals("JPAXD")) {
                this.p = persona;
                servidor.cambiarEstado(nombre, EnumEstado.CONECTADO);
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            throw new UnsupportedOperationException(e.toString());
        }
    }

    public Persona obtenerPersona() throws RemoteException {
        try {
            return p;
        } catch (Exception e) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    public void guardarCombersacion(String nombre, Boolean boo) throws RemoteException  {
        try {
            this.p.setGuardarC(boo);
            servidor.guardarCombersacion(nombre, boo);
        } catch (Exception e) {
            throw new UnsupportedOperationException(e.toString());
        }
    }
}
